package com.cskaoyan.javase.thread._2api;

import sun.management.MappedMXBeanType;

import java.util.concurrent.TimeUnit;

/**
 * 设置守护线程
 * 如何将一个线程设置为守护线程呢？通过Thread类的setDaemon()成员方法。
 * 该方法的方法声明为：
 * public final void setDaemon (boolean on)
 * 将on参数设置为true表示该线程是一个守护线程
 *
 * 说到线程守护，首先我们要认识两种线程的类型：
 * 工作线程（用户线程）：如果不做特殊设置，启动的线程都是工作线程，包括主线程。
 * 守护线程：为工作线程服务的线程，可以理解为工作线程的奴仆。
 *
 * 所谓的守护线程,并不是某个线程的守护线程
 * 而是全体工作线程的守护线程
 * 只有当一个Java进程中的所有工作线程都执行完毕时,守护线程才会退出
 * 只要进程中还有一个工作线程,那么守护线程就会继续工作
 *
 * 工作线程: 主线程,没有做setDaemon (true)操作启动的线程
 * 守护线程: GC的垃圾回收线程
 *
 * 注意事项：
 * 必须在线程启动前将线程设置为守护线程，否则会抛出异常。
 *
 * @since 10:06
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class DaemonDemo {
    public static void main(String[] args) {
        MasterThread mt = new MasterThread("罗峰");
        mt.start();
        // 让主线程继续执行,休眠10s
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MasterThread extends Thread {
    public MasterThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        SlaveThread s1 = new SlaveThread("虫族女皇");
        SlaveThread s2 = new SlaveThread("刀皇");
        SlaveThread s3 = new SlaveThread("剑仙");
        s1.setDaemon(true);
        s2.setDaemon(true);
        s3.setDaemon(true);
        s1.start();
        s2.start();
        s3.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + "正在第" + (i + 1) + "次冲击宇宙最强者!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(getName() + "冲击失败,寄了(主人线程执行完毕!)");
    }
}

// 奴仆线程
class SlaveThread extends Thread {
    public SlaveThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        while (true) {
            System.out.println(getName() + "为主人突破护法!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}